package com.czmh.etc.onlinepubsys.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.czmh.etc.common.core.annotation.ApiVersion;
import com.czmh.etc.common.core.utils.JwtUtil;
import com.czmh.etc.onlinepubsys.configuration.WxAppletConfig;
import com.czmh.etc.onlinepubsys.constants.GlobalStatusCode;
import com.czmh.etc.onlinepubsys.constants.HttpStatusCode;
import com.czmh.etc.onlinepubsys.constants.RedisKey;
import com.czmh.etc.onlinepubsys.json.JsonResult;
import com.czmh.etc.onlinepubsys.json.mingchuang.JSONResult;
import com.czmh.etc.onlinepubsys.jy.utils.Query;
import com.czmh.etc.onlinepubsys.model.AppVersion;
import com.czmh.etc.onlinepubsys.model.EtcDevice;
import com.czmh.etc.onlinepubsys.model.EtcUser;
import com.czmh.etc.onlinepubsys.request.WechatLoginRequest;
import com.czmh.etc.onlinepubsys.services.AppVersionService;
import com.czmh.etc.onlinepubsys.request.WechatLoginRequest;
import com.czmh.etc.onlinepubsys.services.EtcOrderService;
import com.czmh.etc.onlinepubsys.services.EtcUserInfoSevice;
import com.czmh.etc.onlinepubsys.services.ISsoService;
import com.czmh.etc.onlinepubsys.utils.*;
import com.czmh.etc.onlinepubsys.utils.httpclient.HttpUtil;
import com.czmh.etc.onlinepubsys.utils.httpclient.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName：SsoController
 * @Description：登录控制器 
 * @Author： sevenchen. 
 * @Date：2019/10/14 10:35. 
 * @Version：1.0.0
 */
@RestController
@RequestMapping("/{version}/api/sso/")
@Api(tags = "ETC登录接口【新】")
public class SsoController {
    @Autowired
    private WxAppletConfig config;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private ISsoService ssoService;
    @Autowired
    private AppVersionService appVersionService;

    @Autowired
    private EtcUserInfoSevice etcUserInfoSevice;

    @Autowired
    private EtcOrderService orderService;

    @ApiVersion(1)
    @PostMapping(value = "login")
    @ApiOperation(value = "用户登录", notes = "用户登录")
    public JsonResult login(@RequestParam(required = false) String mobile,
                            @RequestParam(required = false) String validCode,
                            @RequestParam(required = false) String code,
                            @RequestParam(required = false) String state,
                            @RequestParam(required = false) boolean force) throws Exception {
        Object token = redisUtil.get(RedisKey.LONGIN_ONLY_KEY + mobile);

        if (force) { //强制登陆
            redisUtil.del(RedisKey.APP_TOKEN + String.valueOf(token));
            token = null;
        }

        if (token != null) { //已在别的设备上登陆
            return JsonResultUtil.toErrorResult("不支持同时登陆多台设备");
        }

        // 1.判断是否为微信授权登录,code不为空则为微信授权登录
        if (StringUtils.isNotEmpty(code)) {
            return ssoService.loginAuthWx(code);
        } else {
            // 手机号+验证码登录
            String redisValidCode = String.valueOf(redisUtil.get(mobile));
            if (StringUtils.isNotEmpty(validCode) && StringUtils.isNotEmpty(redisValidCode)
                    && (validCode.equals(redisValidCode))) {
                if ((redisUtil.get("unCheckPhoneList") != null ? String.valueOf(redisUtil.get("unCheckPhoneList")) : "").indexOf(mobile) == -1) {
                    // 注销验证码
                    redisUtil.del(mobile);
                }
                return ssoService.loginByMobile(mobile);
            } else {
                return JsonResultUtil.toErrorResult("手机验证码不正确！");
            }
        }
    }
    
    @ApiVersion(1)
    @PostMapping("/applet/login")
    @ApiOperation(value = "小程序登录")
    public JsonResult appletLogin(@RequestBody WechatLoginRequest request) throws Exception {
        if (StringUtils.isEmpty(request.getCode())) {
            return JsonResultUtil.toErrorResult("无效code");
        }
        // 向微信服务器使用登录凭证 code 获取 session_key 和 openid
        Map<String, String> params = new HashMap<>(0);
        params.put("appid", config.getAppId());
        params.put("secret", config.getAppSecret());
        params.put("js_code", request.getCode());
        params.put("grant_type", "authorization_code");
        Map<String, String> headers = new HashMap<>(0);
        Result result = HttpUtil.httpGet(config.getOpenidUrl(), headers, params);
        if (result.getStatusCode() == HttpStatusCode.STATUS_200) {
            //解析相应内容（转换成json对象）
            JSONObject json = JSONObject.parseObject(result.getBody());
            //获取会话密钥（session_key）
            String session_key = json.get("session_key").toString();
            String userinfo = AesUtil.decrypt(request.getEncryptedData(), session_key, request.getIv(), "UTF-8");
            if (StringUtils.isNotEmpty(userinfo)) {
                // 调用小程序登录方法处理登录逻辑
                return ssoService.loginByApplet(userinfo);
            } else {
                return JsonResultUtil.toErrorResult("登录失败");
            }
        } else {
            return JsonResultUtil.toErrorResult("登录失败");
        }
    }

    @ApiVersion(1)
    @GetMapping("sendCode/{mobile}")
    @ApiOperation(value = "发送验证码")
    public JsonResult sendverificationcode(@PathVariable String mobile) {
        if ("18520208888".equals(mobile)) {
            return JsonResultUtil.toResult("666888");
        }

        String code = AliSmsUtil.sendPhoneVerificationcode(mobile);
        if (GlobalStatusCode.SUCCESS.equals(code)) {
            return JsonResultUtil.toResult();
        } else {
            return JsonResultUtil.toResult(code);
        }
    }
    
    @ApiVersion(1)
    @PostMapping("outlogin")
    @ApiOperation(value = "退出登录")
    public JsonResult outlogin(@RequestParam String mobile, @RequestParam String token) {
        redisUtil.del(RedisKey.APP_TOKEN + token);
        //注销登陆状态
        redisUtil.del(RedisKey.LONGIN_ONLY_KEY+mobile);
        return ssoService.outlogin(mobile);
    }

    @ApiVersion(1)
    @PostMapping("checkLoginState")
    @ApiOperation(value = "退出登录")
    public JsonResult checkLoginState(@RequestParam String token) {
        JsonResult result = JsonResultUtil.toResult();

        boolean flag = redisUtil.hasKey(RedisKey.APP_TOKEN + token);
        if (flag) {
            result.setStatus(true);
            result.setMessage("有效");
        } else {
            result.setStatus(false);
            result.setMessage("已失效");
        }
        return result;
    }

    @ApiVersion(1)
    @PostMapping("checkVip")
    @ApiOperation(value = "是否VIP")
    public JsonResult checkVip(@RequestParam String mobile) {
        return ssoService.checkVip(mobile);
    }

    @ApiVersion(1)
    @PostMapping("queryAppVersion")
    @ApiOperation(value = "查询app版本")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "int", name = "type", value = "1-android、2-ios,3-小程序", required = true),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "clientVersion", value = "客户端当前版本号", required = true)
    })
    public JsonResult queryAppVersion(@RequestParam(required = true) Integer type, @RequestParam(required = true) String clientVersion) {
        JsonResult r = new JsonResult();
        if(type == null){
            type = 0;
        }
        if(null == clientVersion){
            r.setCode(JSONResult.FAIL);
            r.setMessage("客户端当前版本号不能为空");
            return r;
        }
        try{
            AppVersion appVersion =null;
            List<AppVersion> list = appVersionService.getAppVersionsByType(type);
            //判断使用升级版本
            if(list.size() == 1){
                appVersion= list.get(0);
            }else{
                //弹框升级list
                List<AppVersion> remindList = new ArrayList<>();
                //默认升级list
                List<AppVersion> autoList = new ArrayList<>();
                for(AppVersion app : list){
                    if(appVersionService.compareVersion(app.getVersionName(),clientVersion) > 0){
                        if(app.getStatus() == 2){
                            appVersion = app;
                            break;
                        }else if(app.getStatus() == 0){
                            remindList.add(app);
                        }else if(app.getStatus() == 1){
                            autoList.add(app);
                        }
                    }
                }
                //没有强制升级，则检测弹框升级，再次之，检测默认升级
                if(appVersion == null && remindList.size() >0){
                    appVersion = remindList.get(remindList.size()-1);
                }else if(appVersion == null && autoList.size() >0 && remindList.size() == 0){
                    appVersion = autoList.get(autoList.size()-1);
                }
            }

            //升级信息，只修改强制状态，其他信息展示最新信息
            if(org.apache.commons.collections.CollectionUtils.isNotEmpty(list) && appVersion != null){
                AppVersion lastAppVersion = list.get(list.size() - 1);
                lastAppVersion.setStatus(appVersion.getStatus());
                appVersion = lastAppVersion;
            }

            if (appVersion != null) {
                r.setCode(JSONResult.SUCCESS);
                r.setData(appVersion);
                return r;
            } else if(appVersion == null && list != null && list.size() > 0){
                r.setCode(JSONResult.SUCCESS);
                return r;
            }else {
                r.setCode(JSONResult.FAIL);
                r.setMessage("版本信息获取失败");
                return r;
            }
        }catch (Exception e){
            e.printStackTrace();
            r.setCode(JSONResult.FAIL);
            r.setMessage("版本信息获取失败");
            return r;
        }
    }


    @ApiVersion(1)
    @PostMapping("checkPassword")
    @ApiOperation(value = "根据手机号码判断用户是否设置密码，0密码为空，1已设置密码，2号码不存在")
        public JsonResult checkPassword(@RequestParam String mobile) {
        return ssoService.checkPassword(mobile);
    }

    @ApiVersion(1)
    @PostMapping(value = "loginByPassword")
    @ApiOperation(value = "用户密码登录", notes = "用户密码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "mobile", value = "手机号码", required = true),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "password", value = "密码", required = true),
            @ApiImplicitParam(paramType = "query", dataType = "boolean", name = "force", value = "是否强制登陆", required = true)
    })
    public JsonResult loginByPassword(@RequestParam(required = true) String mobile,
                            @RequestParam(required = true) String password,
                            @RequestParam(required = true) boolean force) throws Exception {
        if (StringUtils.isEmpty(password) || StringUtils.isEmpty(mobile)) {
            return JsonResultUtil.toErrorResult("请完善手机号码和密码");
        }
        Object token = redisUtil.get(RedisKey.LONGIN_ONLY_KEY + mobile);

        if (force) { //强制登陆
            redisUtil.del(RedisKey.APP_TOKEN + String.valueOf(token));
            token = null;
        }

        if (token != null) { //已在别的设备上登陆
            return JsonResultUtil.toErrorResult("不支持同时登陆多台设备");
        }
        return ssoService.loginByPassword(mobile, password);
    }

    @ApiVersion(1)
    @PostMapping(value = "changePassword")
    @ApiOperation(value = "修改密码", notes = "修改密码")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "mobile", value = "手机号码", required = true),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "validCode", value = "验证码", required = true),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "password", value = "密码", required = true)
    })
    public JsonResult changePassword(@RequestParam(required = true) String mobile,
                            @RequestParam(required = true) String validCode,
                            @RequestParam(required = true) String password) throws Exception {
        if (StringUtils.isEmpty(password)) {
            return JsonResultUtil.toErrorResult("请完善密码");
        } else {
            EtcUser etcUser = etcUserInfoSevice.queryUserByMobile(mobile);
            if (etcUser == null){
                return JsonResultUtil.toErrorResult("用户不存在");
            }
            // 手机号+验证码登录
            String redisValidCode = String.valueOf(redisUtil.get(mobile));
            if (StringUtils.isNotEmpty(validCode) && StringUtils.isNotEmpty(redisValidCode)
                    && (validCode.equals(redisValidCode))) {
                if (!"18520208888".equals(mobile)) {
                    // 注销验证码
                    redisUtil.del(mobile);
                }
                return ssoService.changePassword(mobile, password);
            } else {
                return JsonResultUtil.toErrorResult("手机验证码不正确！");
            }
        }
    }

    @ApiVersion(1)
    @PostMapping(value = "updatePassword")
    @ApiOperation(value = "修改密码-不需要验证码", notes = "修改密码-不需要验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "mobile", value = "手机号码", required = true),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "password", value = "密码", required = true)
    })
    public JsonResult updatePassword(@RequestParam(required = true) String mobile,
                                     @RequestParam(required = true) String password) throws Exception {
        if (StringUtils.isEmpty(password)) {
            return JsonResultUtil.toErrorResult("请完善密码");
        } else {
            EtcUser etcUser = etcUserInfoSevice.queryUserByMobile(mobile);
            if (etcUser == null){
                return JsonResultUtil.toErrorResult("用户不存在");
            }
            return ssoService.changePassword(mobile, password);
        }
    }

    /**
     * 先从redis获取对应的产品信息，没有则查询数据库
     * @param obuDeviceSn
     * @return
     * @throws Exception
     */
    @ApiVersion(1)
    @PostMapping(value = "queryProductSnByObuSn")
    @ApiOperation(value = "根据Obu信息查询对应的产品编码", notes = "根据Obu信息查询对应的产品编码")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "obuDeviceSn", value = "Obu编码", required = true)
    })
    public JsonResult queryProductSnByObuSn(@RequestParam(required = true) String obuDeviceSn) throws Exception {
        if (StringUtils.isEmpty(obuDeviceSn)) {
            return JsonResultUtil.toErrorResult("请完善查询信息");
        } else {
            String productSn = "";
            try{
                //读取设备信息
                Object object = redisUtil.get(RedisKey.OBU_KEY + obuDeviceSn);
                productSn = object == null ? "" : object.toString();
            }catch (Exception e){
                e.printStackTrace();
            }
            if(StringUtils.isNotEmpty(productSn)){
                Map<String, Object> result = new HashMap<>();
                result.put("productSn", productSn);
                return JsonResultUtil.toResult(result);
            }else{
                Map<String, Object> queryMap = new HashMap<>();
                queryMap.put("deleteFlag", "0");
                queryMap.put("obuDeviceSn", obuDeviceSn);
                EtcDevice etcDevice = orderService.queryObject(queryMap);
                if(null != etcDevice){
                    Map<String, Object> result = new HashMap<>();
                    result.put("productSn", etcDevice.getProductSn());
                    try{
                        //设备信息存放到redis
                        redisUtil.set(RedisKey.OBU_KEY + obuDeviceSn, etcDevice.getProductSn(), 0L);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    return JsonResultUtil.toResult(result);
                }else{
                    return JsonResultUtil.toErrorResult("请完善查询信息!");
                }
            }
        }
    }

}
